#include "drawview.h"
#include <qdebug.h>

DrawView::DrawView(QWidget *parent) : QGraphicsView (parent)
{
    setAutoFillBackground(true);
    setPalette(QPalette(Qt::white));
    setMinimumSize(800, 600);
    scene.setSceneRect(0, 0, width(), height());
    existitems.clear();
    deleteitems.clear();
    tempItem = NULL;
    setAlignment(Qt::AlignLeft|Qt::AlignTop);
    setScene(&scene);
    mode = draw;
}

void DrawView::setMode(Mode m){
    mode = m;
}

void DrawView::setStyle(int s){
    style = s;
}

void DrawView::setWidth(int w){
    weight = w;
}

void DrawView::setColor(QColor c){
    color = c;
}

void DrawView::setBColor(QColor c){
    b_color = c;
}

void DrawView::setCheckBox(int cb){
     brushCheck = cb;
}

void DrawView::setAddColorTag(bool b){
    addColor = b;
    this->setMouseTracking(b);//设置为不按下鼠标键触发moveEvent
}

void DrawView::setSize(int w, int h)
{
    this->w = w;
    this->h = h;
}

void DrawView::addImage(){
    QString filename = QFileDialog::getOpenFileName
            (this, tr("打开图片"), ".", tr("Image File (*.jpg, *.png *.bmp)"));
    if (QImage().load(filename)) {
        QPixmap image(filename);
        if (image.width() > width()) {
            scene.setSceneRect(0, 0, image.width(), sceneRect().height());
        }
        if (image.height() > height()) {
            scene.setSceneRect(0, 0, sceneRect().width(), image.height());
        }
        QGraphicsPixmapItem *pix = new QGraphicsPixmapItem(image);
        pix->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(pix);
    }
}

void DrawView::saveImage(){
    QString filename1 = QFileDialog::getSaveFileName(this,tr("保存图片"),"",tr("Images (*.png)")); //选择路径
    QImage image(810, 610, QImage::Format_ARGB32);
    QPainter painter(&image);
    scene.render(&painter);   //关键函数
    image.save(filename1);
}

void DrawView::clear(){
    if(scene.focusItem() != 0){
        scene.removeItem(scene.focusItem());
        scene.update();
        return;
    }
    else
        scene.clear();
        existitems.clear();
        deleteitems.clear();
        scene.update();
}

//取消
void DrawView::undo(){
    if(!existitems.isEmpty()){
        QGraphicsItem *temp = existitems.pop();
        scene.removeItem(temp);
        deleteitems.push(temp);
        scene.update();
    }
    else {
        return;
    }
}

//重做
void DrawView::redo(){
    if(!deleteitems.isEmpty()){
        QGraphicsItem *temp = deleteitems.pop();
        scene.addItem(temp);
        existitems.push(temp);
        scene.update();
    }
    else {
        return;
    }
}

void DrawView::keyPressEvent(QKeyEvent *e) {
    if (e->key() == Qt::Key_Delete) {
        scene.removeItem(scene.focusItem());
    }
}


void DrawView::mousePressEvent(QMouseEvent *e){
    QPointF ePos = mapToScene(e->pos());
    if(addColor){
        //填充颜色 -- 泛洪填充算法
        this->floodFill4(ePos.x(), ePos.y(), color, this->getRecordColor(ePos.x(), ePos.y()));
    }else{
    switch (mode){
    case empty :
    {
        break;
    }
    case draw :
    {
//        if(startPos.x() == ePos.x() && startPos.y() == ePos.y()){
            //绘制点
            QGraphicsLineItem *point = new QGraphicsLineItem(QLine(ePos.x(), ePos.y(), ePos.x(), ePos.y()));
            QPen pen;
            pen.setStyle(Qt::PenStyle(style));
            pen.setWidth(weight);
            pen.setColor(color);
            point->setPen(pen);
            scene.addItem(point);
            existitems.push(point);
//        }
        startPos = ePos;
        break;
    }
    case line :
    {
        startPos = ePos;
        break;
    }
    case curve :
    {
        startPos = ePos;
        break;
    }
    case rectangle :
    {
        startPos = ePos;
        break;
    }
    case roundrect :
    {
        startPos = ePos;
        break;
    }
    case circle:
    {
        startPos = ePos;
        break;
    }
    case ellipse :
    {
        startPos = ePos;
        break;
    }
    case choose :
    {
        QGraphicsView::mousePressEvent(e);
        break;
    }
    }
    }
}

void DrawView::mouseMoveEvent(QMouseEvent *e){
    QPointF ePos = mapToScene(e->pos());
    if(addColor){
        if(ePos.rx() > 0 && ePos.rx() < this->w && ePos.ry() > 0 && ePos.ry() < this->h)
        {
            QCursor *myCursor=new QCursor(QPixmap(":/image/brushColor.png"),-1,-1);    //-1,-1表示热点位于图片中心
            this->setCursor(*myCursor);
        }else {
            this->setCursor(Qt::CrossCursor);
        }
    }else{
    switch (mode){
    case empty :
    {
        break;
    }
    case draw :
    {
        QGraphicsLineItem *point = new QGraphicsLineItem(QLineF(startPos.x(), startPos.y(), ePos.x(), ePos.y()));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        point->setPen(pen);
        scene.addItem(point);
        existitems.push(point);
//        startPos = e->pos();
        startPos = ePos;
        break;
    }
    case line :
    {
        if (items.size() != 0){//鼠标每移动一次都会画一个新的图元，只保留最后一次移动画出的图元，其余都要删除
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        QGraphicsLineItem *line = new QGraphicsLineItem(QLineF(startPos.x(), startPos.y(), ePos.x(), ePos.y()));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        line->setPen(pen);
        line->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(line);
        tempItem = line;
        items.insert(line);
        scene.update();
        break;
    }
    case curve :
    {
        if (items.size() != 0){
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        CurveItem *curve = new CurveItem(QLineF(startPos.x(), startPos.y(), ePos.x(), ePos.y()));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        curve->setPen(pen);
        curve->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(curve);
        tempItem = curve;
        items.insert(curve);
        scene.update();
        break;
    }
    case rectangle :
    {
        if (items.size() != 0){
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        qreal width = ePos.x() - startPos.x();
        qreal height = ePos.y() - startPos.y();
        qreal x = width > 0 ? startPos.x() : startPos.x() + width;
        qreal y = height > 0 ? startPos.y() : startPos.y() + height;
        QGraphicsRectItem *rect = new QGraphicsRectItem(x, y, std::abs(width), std::abs(height));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        rect->setPen(pen);
        if(brushCheck == 1){
            rect->setBrush(QBrush(b_color));
        }
        rect->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(rect);
        tempItem = rect;
        items.insert(rect);
        scene.update();
        for(int i = startPos.x(); i<=ePos.x();i++){
            this->setRecordColor(color, i, startPos.y());
            this->setRecordColor(color, i, ePos.y());
        }
        for(int i = startPos.y(); i<=ePos.y();i++){
            this->setRecordColor(color, startPos.x(), i);
            this->setRecordColor(color, ePos.x(), i);
        }
        break;
    }
    case roundrect :
    {
        if (items.size() != 0){
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        qreal width = ePos.x() - startPos.x();
        qreal height = ePos.y() - startPos.y();
        qreal x = width > 0 ? startPos.x() : startPos.x() + width;
        qreal y = height > 0 ? startPos.y() : startPos.y() + height;
        RoundRectItem *rRect = new RoundRectItem(x, y, std::abs(width), std::abs(height));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        rRect->setPen(pen);
        if(brushCheck == 1){
            rRect->setBrush(QBrush(b_color));
        }
        rRect->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(rRect);
        tempItem = rRect;
        items.insert(rRect);
        scene.update();
        break;
    }
    case circle:
    {
        if (items.size() != 0){
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        qreal width = ePos.x() - startPos.x();
        qreal height = (ePos.y() > startPos.y()) ? std::abs(width) : -std::abs(width);
        QGraphicsEllipseItem *circle = new QGraphicsEllipseItem(startPos.x(), startPos.y(), width, height);
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        circle->setPen(pen);
        if(brushCheck == 1){
            circle->setBrush(QBrush(b_color));
        }
        circle->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(circle);
        tempItem = circle;
        items.insert(circle);
        scene.update();
        break;
    }
    case ellipse :
    {
        if (items.size() != 0){
            foreach (QGraphicsItem *item, items){
                delete item;
                item = nullptr;
            }
            items.clear();
        }
        qreal width = ePos.x() - startPos.x();
        qreal height = ePos.y() - startPos.y();
        qreal x = width > 0 ? startPos.x() : startPos.x() + width;
        qreal y = height > 0 ? startPos.y() : startPos.y() + height;
        QGraphicsEllipseItem *ellipse = new QGraphicsEllipseItem(x, y, std::abs(width), std::abs(height));
        QPen pen;
        pen.setStyle(Qt::PenStyle(style));
        pen.setWidth(weight);
        pen.setColor(color);
        ellipse->setPen(pen);
        if(brushCheck == 1){
            ellipse->setBrush(QBrush(b_color));
        }
        ellipse->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
        scene.addItem(ellipse);
        tempItem = ellipse;
        items.insert(ellipse);
        scene.update();
        break;
    }
    case choose :
    {
        QGraphicsView::mouseMoveEvent(e);
        break;
    }
    }
    }
}

void DrawView::mouseReleaseEvent(QMouseEvent *e)
{
    switch (mode){
    case empty :
    {
        break;
    }
    case draw :
    {
        break;
    }
    case line :
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case curve :
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case rectangle :
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case roundrect :
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case circle:
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case ellipse :
    {
        existitems.push(tempItem);
        items.clear();
        break;
    }
    case choose :
    {
        QGraphicsView::mouseReleaseEvent(e);
        scene.update();
        break;
    }
    }
}

//泛洪填充算法
void DrawView::floodFill4(int x, int y, QColor newColor, QColor oldColor){
    if(x >= 0 && x <= 1000 && y >= 0 && y <= 1000 && this->getRecordColor(x,y)!=newColor && this->getRecordColor(x,y)==oldColor ){
        this->fillColor(x, y, newColor); //set color before starting recursion
        floodFill4(x + 1, y,     newColor, oldColor);
        floodFill4(x - 1, y,     newColor, oldColor);
        floodFill4(x,     y + 1, newColor, oldColor);
        floodFill4(x,     y - 1, newColor, oldColor);
    }
}

void DrawView::fillColor(int x, int y, QColor newColor){
    QGraphicsLineItem *point = new QGraphicsLineItem(QLine(x, y, x, y));
    QPen pen;
    pen.setStyle(Qt::PenStyle(style));
    pen.setWidth(weight);
    pen.setColor(newColor);
    //记录当前填充的颜色
    this->setRecordColor(newColor, x, y);
    point->setPen(pen);
    scene.addItem(point);
//    existitems.push(point);
}

void DrawView::setRecordColor(QColor c, int x, int y)
{
    this->recordColor[x][y] = c;
}

QColor DrawView::getRecordColor(int x, int y){
    return recordColor[x][y];
}
